package com.qufadai.framework.orm.jdbc;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Mapping tool use to parse Class info into Table info container
 */
public class JdbcParser {
	//cann't construct instance
	private JdbcParser(){}
	private static final int PRIVATE_FIELD = 2;
	
	public static TableDefinition parseClass(Class<?> target) {
		boolean hasTable = target.isAnnotationPresent(Table.class);
		Table table = null;
		if(hasTable) {
			table = (Table)target.getAnnotation(Table.class);
		}
		Field[] fields = target.getDeclaredFields();
		Map<String, Column> columns = new HashMap<String, Column>();
		for(int i = 0; i < fields.length; i++) {
			if(fields[i].getModifiers() == PRIVATE_FIELD && fields[i].isAnnotationPresent(Column.class)) {
				columns.put(fields[i].getName(), fields[i].getAnnotation(Column.class));
			}
		}
		//create TableDefinition
		if(table != null && columns.size() > 0) {
			TableDefinition definition = new TableDefinition();
			definition.setTableName(table.name());
			Set<String> keys = columns.keySet();
			for(String fieldName : keys) {
				Column colDef = columns.get(fieldName);
				// key为Java字段名,value为相应的表字段.例filedName:username,colDef.name():USER_NAME
				definition.getColumns().put(fieldName,colDef.name());
				definition.getColType().put(fieldName,colDef.type());
				String constraint = "";
				if(colDef.isPrimaryKey()) {
					constraint += " PRIMARY KEY";
				} else {
					if(colDef.isNullable()) {
						constraint += " NOT NULL";
					}
					if(colDef.isUnique()) {
						constraint += " UNIQUE";
					}
				}
				definition.getConstraint().put(fieldName, constraint);
			}
			return definition;
		}
		
		return null;
	}
	
	public static String parserQuery(String id, String tableName){
	    StringBuilder sqlSB = new StringBuilder();
	    sqlSB.append("SELECT * FROM ");
	    sqlSB.append(tableName);
	    sqlSB.append(" WHERE ID='");
	    sqlSB.append(id);
	    sqlSB.append("'");
	    
	    return sqlSB.toString().trim();
	}
	
	public static String parseTable(TableDefinition tabDef) {
		if(tabDef == null) {
			return null;
		}
		StringBuilder sqlSB = new StringBuilder();
		sqlSB.append("CREATE TABLE ");
		sqlSB.append(tabDef.getTableName());
		sqlSB.append("(");
		Set<String> columns = tabDef.getColumns().keySet();
		for(String key : columns) {
			sqlSB.append(tabDef.getColumns().get(key));
			sqlSB.append(" "+tabDef.getColType().get(key));
			sqlSB.append(" "+tabDef.getConstraint().get(key));
			sqlSB.append(",");
		}
		sqlSB.deleteCharAt(sqlSB.length()-1);
		sqlSB.append(")");
		
		return sqlSB.toString().trim();
	}
	
	public static String parseInsert(TableDefinition tabDef){
	    if(tabDef == null) {
	        return null;
	    }
	    StringBuilder sqlSB = new StringBuilder();
	    sqlSB.append("INSERT INTO ");
	    sqlSB.append(tabDef.getTableName());
	    sqlSB.append("(");
	    Set<String> columns = tabDef.getColumns().keySet();
	    for(String key : columns) {
	        sqlSB.append(tabDef.getColumns().get(key)+",");
	    }
	    sqlSB.deleteCharAt(sqlSB.length()-1);
	    sqlSB.append(") VALUES(");
	    int size = columns.size();
	    for(int i = 0; i < size; i++) {
	        sqlSB.append("?,");
	    }
	    sqlSB.deleteCharAt(sqlSB.length()-1);
	    sqlSB.append(")");
	    
	    return sqlSB.toString().trim();
	}
	
	public static String parserUpdate(TableDefinition tableDef) {
        if(tableDef == null)
            return null;
        
        StringBuilder sqlSB = new StringBuilder();
        sqlSB.append("UPDATE ");
        sqlSB.append(tableDef.getTableName());
        sqlSB.append(" SET ");
        
        Set<String> columns = tableDef.getColumns().keySet();
        for(String key : columns){
            if("id".equalsIgnoreCase(key))
                continue;
            
            sqlSB.append(tableDef.getColumns().get(key));
            sqlSB.append("=?,");
        }
        
        sqlSB.deleteCharAt(sqlSB.length()-1);
        sqlSB.append(" WHERE ID=?");
        
        return sqlSB.toString().trim();
    }

    public static String parseDelete(String tableName, String id) {
        StringBuilder sqlSB = new StringBuilder();
        sqlSB.append("DELETE FROM ");
        sqlSB.append(tableName);
        sqlSB.append(" WHERE ID='");
        sqlSB.append(id+"'");
        
        return sqlSB.toString().trim();
    }

    public static String parserQuery(String tableName) {
        StringBuilder sqlSB = new StringBuilder();
        sqlSB.append("SELECT * FROM ");
        sqlSB.append(tableName);
        return sqlSB.toString().trim();
    }

    public static String parserQuery(QueryDefinition query, TableDefinition def) {
        StringBuilder sqlSB = new StringBuilder();
        String tableName = def.getTableName();
        sqlSB.append("SELECT ");
        Set<String> fields = query.getColumns();
        for(String field : fields) {
            sqlSB.append(def.getColumns().get(field));
            sqlSB.append(",");
        }
        sqlSB.deleteCharAt(sqlSB.length()-1);
        sqlSB.append(" FROM ");
        sqlSB.append(tableName);
        if(!query.getConditions().isEmpty()) {
            sqlSB.append(" WHERE ");
            Set<String> conditionKeys = query.getConditions().keySet();
            for(String conditionKey : conditionKeys) {
                sqlSB.append(def.getColumns().get(conditionKey));
                sqlSB.append(query.getConditions().get(conditionKey));
                sqlSB.append(" AND ");
            }
            sqlSB.delete(sqlSB.length()-5, sqlSB.length());
        }
        if(!query.getConstraint().isEmpty()) {
            sqlSB.append(" ");
            sqlSB.append(query.getConstraint());
        }
        
        return sqlSB.toString().trim();
    }
}
